package com.evil.kingdom.service.person.base.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.evil.common.core.exception.BusinessException;
import com.evil.common.core.util.StreamUtil;
import com.evil.kingdom.pojo.dto.core.ArmDto;
import com.evil.kingdom.pojo.dto.core.ItemDto;
import com.evil.kingdom.pojo.dto.core.MountDto;
import com.evil.kingdom.pojo.dto.person.base.PersonDto;
import com.evil.kingdom.pojo.entity.person.base.Person;
import com.evil.kingdom.pojo.enums.PersonTypeEnum;
import com.evil.kingdom.pojo.enums.result.RCodeEnum;
import com.evil.common.mongo.service.impl.SingleServiceImpl;
import com.evil.kingdom.repository.person.base.PersonRepository;
import com.evil.kingdom.service.core.ArmService;
import com.evil.kingdom.service.core.ItemService;
import com.evil.kingdom.service.core.MountService;
import com.evil.kingdom.service.person.base.PersonService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 人物
 *
 * @author liyang
 * @date 2024-05-22 16:53
 */
@Slf4j
@Service
@AllArgsConstructor
public class PersonServiceImpl extends SingleServiceImpl<PersonRepository, Person> implements PersonService {

    private final ArmService armService;
    private final ItemService itemService;
    private final MountService mountService;

    @Override
    public Person add(Person person) {
        if (null != person.getArm() && armService.existsByName(person.getArm())) {
            String msg = armService.notExistMsg(person.getArm());
            log.error("person|add|arm not exit|error|msg:{}", msg);
            throw new BusinessException(RCodeEnum.ENTITY_NOT_EXIST, msg);
        }
        if (null != person.getItem() && itemService.existsByName(person.getItem())) {
            String msg = itemService.notExistMsg(person.getArm());
            log.error("person|add|item not exit|error|msg:{}", msg);
            throw new BusinessException(RCodeEnum.ENTITY_NOT_EXIST, msg);
        }
        if (null != person.getMount() && mountService.existsByName(person.getMount())) {
            String msg = mountService.notExistMsg(person.getArm());
            log.error("person|add|mount not exit|error|msg:{}", msg);
            throw new BusinessException(RCodeEnum.ENTITY_NOT_EXIST, msg);
        }
        return super.add(person);
    }

    @Override
    public PersonDto findDtoByName(String name) {
        return this.findDtoByPerson(this.findByName(name));
    }

    @Override
    public PersonDto findDtoByPerson(Person person) {
        PersonTypeEnum personTypeEnum = PersonTypeEnum.findByType(person.getType());
        PersonDto personDto = BeanUtil.copyProperties(person, PersonDto.class);
        Optional.ofNullable(person.getArm()).ifPresent(n -> personDto.setArmDto(armService.findDtoByName(n)));
        Optional.ofNullable(person.getItem()).ifPresent(n -> personDto.setItemDto(itemService.findDtoByName(n)));
        Optional.ofNullable(person.getMount()).ifPresent(n -> personDto.setMountDto(mountService.findDtoByName(n)));
        personDto.setTypeEnum(personTypeEnum);
        return personDto;
    }

    @Override
    public List<PersonDto> findDtoByNames(Collection<String> names) {
        List<Person> persons = this.findByNames(names);
        if (CollectionUtil.isEmpty(persons)) {
            return new ArrayList<>();
        }

        Set<String> armNames = new HashSet<>();
        Set<String> itemNames = new HashSet<>();
        Set<String> mountNames = new HashSet<>();
        persons.forEach(p -> {
            Optional.ofNullable(p.getArm()).filter(StringUtils::isNotBlank).ifPresent(armNames::add);
            Optional.ofNullable(p.getItem()).filter(StringUtils::isNotBlank).ifPresent(itemNames::add);
            Optional.ofNullable(p.getMount()).filter(StringUtils::isNotBlank).ifPresent(mountNames::add);
        });
        List<ArmDto> arms = armService.findDtoByNames(armNames);
        Map<String, ArmDto> armMap = StreamUtil.toMapK(arms, ArmDto::getName);
        List<ItemDto> items = itemService.findDtoByNames(itemNames);
        Map<String, ItemDto> itemMap = StreamUtil.toMapK(items, ItemDto::getName);
        List<MountDto> mounts = mountService.findDtoByNames(mountNames);
        Map<String, MountDto> mountMap = StreamUtil.toMapK(mounts, MountDto::getName);

        return persons.stream().map(person -> {
            PersonTypeEnum personTypeEnum = PersonTypeEnum.findByType(person.getType());
            PersonDto personDto = BeanUtil.copyProperties(person, PersonDto.class);
            Optional.ofNullable(person.getArm()).filter(StringUtils::isNotBlank).ifPresent(n -> personDto.setArmDto(armMap.get(n)));
            Optional.ofNullable(person.getItem()).filter(StringUtils::isNotBlank).ifPresent(n -> personDto.setItemDto(itemMap.get(n)));
            Optional.ofNullable(person.getMount()).filter(StringUtils::isNotBlank).ifPresent(n -> personDto.setMountDto(mountMap.get(n)));
            personDto.setTypeEnum(personTypeEnum);
            return personDto;
        }).collect(Collectors.toList());
    }
}
